package gxprod.androidai.functions;

import gxprod.androidai.AIActivity;
import gxprod.androidai.BubbleAdapter;
import gxprod.androidai.regex.MatchResult;
import gxprod.androidai.regex.NamedPattern;
import gxprod.androidai.support.BasicEntry;
import gxprod.androidai.support.Lookup;

import java.util.Date;
import java.util.Vector;

import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;

public class CallFunction extends Function{

	NamedPattern[] patterns = new NamedPattern[] {
			NamedPattern.compile("call(( [\\w]+){1,2})"),
			NamedPattern.compile("call ([0-9\\+\\-\\(\\)]+)"),
			NamedPattern.compile("(who called me|show me my missed calls)")
	};

	@Override
	public boolean cullFunction(String command) {
		return command.contains("call") | command.contains("called");
	}

	@Override
	public MatchResult isMatch(String statement) {
		return super.isMatch(statement, patterns, 0.893f);
	}

	@Override
	public boolean execute(MatchResult match, BubbleAdapter adapter) {
		String number = "";

		switch(match.MatchIndex) {
			case 0:	// call <person>
				String person = match.Matcher.group(1).trim();
				
				Vector<BasicEntry<String, String>> matches = Lookup.lookupIncompleatNamesNumbers(AIActivity.get(), person);
				if(matches.size() == 0) {
					adapter.output("I don't know that person");
					return true;
				} else if(matches.size() == 1) {
					StringBuilder sb = new StringBuilder();					
					number = matches.get(0).getValue();					
					sb.append("Calling <b>");
					sb.append(matches.get(0).getKey());
					sb.append("</b>&lt;");
					sb.append(number);
					sb.append("&gt;");					
					adapter.output(sb.toString(), "calling" + matches.get(0).getKey());
					
				} else if(matches.size() > 1) {
					adapter.output("Be more specific about who you are calling");
					return true;
				}

				Intent callIntent = new Intent(Intent.ACTION_CALL);
				callIntent.setData(Uri.parse("tel:" + number));
				AIActivity.get().startActivity(callIntent);
				return true;

				
			case 1:
				

				
				break;
				
				
			case 2:	// who called me

				Call[] missedCalls = getMissedCallList(AIActivity.get());
				if(missedCalls == null)
					adapter.output("I was unable to find your phones call log");


				if(missedCalls.length == 0) 						// 0
				{
					adapter.output("You have no missed calls");
					return true;
				}

				StringBuilder sb = new StringBuilder();
				StringBuilder sb1 = new StringBuilder();

				sb1.append("You have ");
				sb1.append((missedCalls.length == 1)? "a" : missedCalls.length);
				sb1.append(" missed calls");

				if(missedCalls.length < 3) {					// 1, 2, 3
					sb.append("<ul><li>");
					writeCall(sb, missedCalls[0], true);
					
					for(int j = 1; j < missedCalls.length; j++) {
						sb.append("</li><li>");
						writeCall(sb, missedCalls[j], true);
					}
					sb.append("</ul>");
					
					// -------------- Say ------------- //

					sb1.append(" from");
					if(missedCalls.length == 1) {
						sb1.append(missedCalls[0].Caller);

					} else if(missedCalls.length == 2) {
						sb1.append(missedCalls[0].Caller);
						sb1.append(", and ");
						sb1.append(missedCalls[1].Caller);

					} else if(missedCalls.length == 3) {
						sb1.append(missedCalls[0].Caller);
						sb1.append(", ");
						sb1.append(missedCalls[1].Caller);
						sb1.append(", and ");
						sb1.append(missedCalls[2].Caller);
					}
				}
				else { // if(missedCalls.length >= 3) {
					sb.append("<ul><li>");
					writeCall(sb, missedCalls[0], true);
					
					for(int j = 1; j < Math.min(8, missedCalls.length); j++) {
						sb.append("</li><li>");
						writeCall(sb, missedCalls[j], true);
					}
					sb.append("</li></ul>");
					if(missedCalls.length >= 8)
						sb.append("...");
					
					// -------------- Say ------------- //
					
					sb1.append(". Click on this bubble to see more info.");
				}
				
				String write = sb.toString();
				String say = sb1.toString();

				adapter.output(write, say);
				break;
		}
		return true;
	}

	private void writeCall(StringBuilder sb, Call call, boolean detailed) {

		if(call.Caller == null | call.Caller.length() == 0 | call.Caller.equalsIgnoreCase(call.Number))
			sb.append(call.Number);
		else {
			sb.append(call.Caller);
			if(detailed) {
				sb.append("<i>&lt;");
				sb.append(call.Number);
				sb.append("&gt;</i>");	
			}
		}

	}

	public Call[] getMissedCallList(Context context) {

		String[] strFields = {
				android.provider.CallLog.Calls.NUMBER, 
				android.provider.CallLog.Calls.CACHED_NAME,
				android.provider.CallLog.Calls.NEW, 
				android.provider.CallLog.Calls.DATE,
				android.provider.CallLog.Calls.DURATION,
				android.provider.CallLog.Calls.TYPE,
		};
		String strOrder = android.provider.CallLog.Calls.DATE + " DESC"; 

		Cursor mCallCursor = context.getContentResolver().query(
				android.provider.CallLog.Calls.CONTENT_URI,
				strFields,
				null,
				null,
				strOrder
				);

		Call[] calls = new Call[mCallCursor.getCount()];
		int pos = 0;
		mCallCursor.moveToFirst();

		while (pos < mCallCursor.getCount()) {

			String temp = mCallCursor.getString(mCallCursor.getColumnIndex(strFields[5]));
			if(temp.equalsIgnoreCase("missed")) {				
				calls[pos] = new Call();

				calls[pos].Incomming	= true;								// must be incoming to be missed
				calls[pos].Missed		= true;								// must be missed to be set in this block of code
				calls[pos].Number		= mCallCursor.getString(mCallCursor.getColumnIndex(strFields[0]));
				calls[pos].Caller		= mCallCursor.getString(mCallCursor.getColumnIndex(strFields[1]));
				calls[pos].IsNew		= 0 < mCallCursor.getInt(mCallCursor.getColumnIndex(strFields[2]));
				calls[pos].Date			= new Date(mCallCursor.getLong(mCallCursor.getColumnIndex(strFields[3])));
				calls[pos].Durration	= mCallCursor.getLong(mCallCursor.getColumnIndex(strFields[4]));

				pos++;
			}
			mCallCursor.moveToNext();
		}

		return calls;
	}

	public static class Call {
		public String Number;
		public String Caller;
		public Date Date;
		public long Durration;
		public boolean Incomming;
		public boolean Missed;
		public boolean IsNew;
	}
}
